package cn.iocoder.yudao.module.system.framework.sms.core.client.impl;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.crypto.digest.HmacAlgorithm;
import cn.hutool.http.HttpUtil;
import cn.iocoder.yudao.framework.common.core.KeyValue;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO;
import cn.iocoder.yudao.module.system.controller.admin.sms.vo.log.SmsLogPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.socail.vo.user.SocialUserRespVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileRespVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserPageReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum;
import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsReceiveRespDTO;
import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsSendRespDTO;
import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsTemplateRespDTO;
import cn.iocoder.yudao.module.system.framework.sms.core.enums.SmsTemplateAuditStatusEnum;
import cn.iocoder.yudao.module.system.framework.sms.core.property.SmsChannelProperties;
import cn.iocoder.yudao.module.system.service.sms.SmsLogService;
import cn.iocoder.yudao.module.system.service.social.SocialUserService;
import cn.iocoder.yudao.module.system.service.user.AdminUserService;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import com.aliyun.tea.*;
import com.aliyun.teautil.*;
import com.aliyun.teautil.models.*;
import com.aliyun.dingtalktodo_1_0.*;
import com.aliyun.dingtalktodo_1_0.models.*;
import com.aliyun.teaopenapi.*;
import com.aliyun.teaopenapi.models.*;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.request.OapiGettokenRequest;
import com.dingtalk.api.response.OapiGettokenResponse;
import com.taobao.api.ApiException;
import com.xingyuv.jushauth.exception.AuthException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

/**
 * 基于钉钉 WebHook 实现的调试的短信客户端实现类
 *
 * 考虑到省钱，我们使用钉钉 WebHook 模拟发送短信，方便调试。
 *
 * @author 芋道源码
 */
@Slf4j
public class DingTalkSmsClient extends AbstractSmsClient {

    public DingTalkSmsClient(SmsChannelProperties properties) {
        super(properties);
        Assert.notEmpty(properties.getApiKey(), "apiKey 不能为空");
        Assert.notEmpty(properties.getApiSecret(), "apiSecret 不能为空");
    }

    /**
     * 使用 Token 初始化账号Client
     * @return Client
     * @throws Exception
     */
    public static com.aliyun.dingtalktodo_1_0.Client createClient() throws Exception {
        Config config = new Config();
        config.protocol = "https";
        config.regionId = "central";
        return new com.aliyun.dingtalktodo_1_0.Client(config);
    }

    public void main(String[] args_) throws Exception {

    }

    @Override
    public SmsSendRespDTO sendSms(Long sendLogId, String mobile,
                                  String apiTemplateId, List<KeyValue<String, Object>> templateParams) throws Throwable {
        String openid = mobile;
        // 构建请求
        String url = MapUtils.convertMap(templateParams).get("detailUrl").toString();//String.format("https://api.dingtalk.com/v1.0/todo/users/%s/tasks?operatorId=%s",openid, openid);

        //获取token
        DefaultDingTalkClient client0 = new DefaultDingTalkClient("https://oapi.dingtalk.com/gettoken");
        OapiGettokenRequest request = new OapiGettokenRequest();
        request.setAppkey(super.properties.getApiKey());
        request.setAppsecret(super.properties.getApiSecret());
        request.setHttpMethod("GET");

        OapiGettokenResponse rsp0 = null;
        log.info("请求request：{}", request);
        try {
            rsp0 = client0.execute(request);
        } catch (ApiException e) {
            // log.error("getAccessToken failed", e);
            System.out.println(e.toString());
            throw new AuthException(e.getErrMsg());
        }
        log.info("请求返回rsp0：{}", rsp0);
        String accessToken = rsp0.getAccessToken();

        com.aliyun.dingtalktodo_1_0.Client client = createClient();
        CreateTodoTaskHeaders createTodoTaskHeaders = new CreateTodoTaskHeaders();
        createTodoTaskHeaders.xAcsDingtalkAccessToken = accessToken;
        String content = MapUtils.convertMap(templateParams).get("startUserNickname").toString()
                +"提交的"
                +MapUtils.convertMap(templateParams).get("processInstanceName").toString()
                +"，当前节点："
                +MapUtils.convertMap(templateParams).get("taskName").toString();

        CreateTodoTaskRequest.CreateTodoTaskRequestNotifyConfigs notifyConfigs = new CreateTodoTaskRequest.CreateTodoTaskRequestNotifyConfigs()
                .setDingNotify("1");
        CreateTodoTaskRequest.CreateTodoTaskRequestContentFieldList contentFieldList0 = new CreateTodoTaskRequest.CreateTodoTaskRequestContentFieldList();
        CreateTodoTaskRequest.CreateTodoTaskRequestDetailUrl detailUrl = new CreateTodoTaskRequest.CreateTodoTaskRequestDetailUrl()
                .setAppUrl(url)
                .setPcUrl(url);
        CreateTodoTaskRequest createTodoTaskRequest = new CreateTodoTaskRequest()
                .setOperatorId(openid)
                .setSourceId("isv_dingtalkTodo"+sendLogId)
                .setSubject(content)
                .setCreatorId(openid)
                .setDescription("")
//                .setDueTime(1617675000000L)
                .setExecutorIds(java.util.Arrays.asList(
                        openid
                ))
                .setParticipantIds(java.util.Arrays.asList(
                        openid
                ))
                .setDetailUrl(detailUrl)
                .setContentFieldList(java.util.Arrays.asList(
                        contentFieldList0
                ))
                .setIsOnlyShowExecutor(true)
                .setPriority(20)
                .setNotifyConfigs(notifyConfigs);
        String errorCode = "0";
        String errorMsg = "";
        log.info("请求createTodoTaskRequest：{}，createTodoTaskHeaders：{}", createTodoTaskRequest,createTodoTaskHeaders);
        CreateTodoTaskResponse res1 = null;
        try {
            res1 = client.createTodoTaskWithOptions(openid, createTodoTaskRequest, createTodoTaskHeaders, new RuntimeOptions());
        } catch (TeaException err) {
            if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
                // err 中含有 code 和 message 属性，可帮助开发定位问题
                errorCode = err.getCode();
                errorMsg = err.getMessage()+";1请求信息:"+request.toString();
            }

        } catch (Exception _err) {
            TeaException err = new TeaException(_err.getMessage(), _err);
            if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
                // err 中含有 code 和 message 属性，可帮助开发定位问题
                errorCode = err.getCode();
                errorMsg = err.getMessage()+";2请求信息:"+request.toString();
            }

        }
        log.info("请求返回rsp1：{}", res1);
        return new SmsSendRespDTO().setSuccess(Objects.equals(errorCode, "0")).setSerialNo(StrUtil.uuid())
                .setApiCode(errorCode).setApiMsg(errorMsg);

//        //buildUrl("robot/send");
//        Map<String, Object> params = new HashMap<>();
//        params.put("msgtype", "text");
//        String content = String.format("【模拟短信】\n手机号：%s\n短信日志编号：%d\n模板参数：%s",
//                mobile, sendLogId, MapUtils.convertMap(templateParams));
//        params.put("text", MapUtil.builder().put("content", content).build());
//        // 执行请求
//        String responseText = HttpUtil.post(url, JsonUtils.toJsonString(params));
//        // 解析结果
//        Map<?, ?> responseObj = JsonUtils.parseObject(responseText, Map.class);
//        String errorCode = MapUtil.getStr(responseObj, "errcode");
//        return new SmsSendRespDTO().setSuccess(Objects.equals(errorCode, "0")).setSerialNo(StrUtil.uuid())
//                .setApiCode(errorCode).setApiMsg(MapUtil.getStr(responseObj, "errorMsg"));
    }

    /**
     * 构建请求地址
     *
     * 参见 <a href="https://developers.dingtalk.com/document/app/custom-robot-access/title-nfv-794-g71">文档</a>
     *
     * @param path 请求路径
     * @return 请求地址
     */
    @SuppressWarnings("SameParameterValue")
    private String buildUrl(String path) {
        // 生成 timestamp
        long timestamp = System.currentTimeMillis();
        // 生成 sign
        String secret = properties.getApiSecret();
        String stringToSign = timestamp + "\n" + secret;
        byte[] signData = DigestUtil.hmac(HmacAlgorithm.HmacSHA256, StrUtil.bytes(secret)).digest(stringToSign);
        String sign = Base64.encode(signData);
        // 构建最终 URL
        return String.format("https://oapi.dingtalk.com/%s?access_token=%s&timestamp=%d&sign=%s",
                path, properties.getApiKey(), timestamp, sign);
    }

    @Override
    public List<SmsReceiveRespDTO> parseSmsReceiveStatus(String text) {
        throw new UnsupportedOperationException("模拟短信客户端，暂时无需解析回调");
    }

    @Override
    public SmsTemplateRespDTO getSmsTemplate(String apiTemplateId) {
        return new SmsTemplateRespDTO().setId(apiTemplateId).setContent("")
                .setAuditStatus(SmsTemplateAuditStatusEnum.SUCCESS.getStatus()).setAuditReason("");
    }

}
